/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */

import { Worker } from 'worker_threads';

import { WorkerState } from '../enum/worker-state.js';
import { Work } from '../model/work.js';

export interface TaskInfo {
  hasSideEffects: boolean;
  preludeDeps: string[];
}

/**
 * 管理单个worker的状态
 *
 * @since 2022/8/15
 */
export class HWorker {
  private worker: Worker;
  private readonly id: number;
  private state: WorkerState;
  private lastBusyTime: number;
  private curWorkId: string | undefined;
  private melted = false;
  private curTaskInfo: TaskInfo | undefined;
  private cacheSize = 0;

  constructor(worker: Worker, id: number) {
    this.worker = worker;
    this.id = id;
    this.state = WorkerState.IDLE;
    this.lastBusyTime = Date.now();
  }

  /**
   * 获取worker状态
   *
   * @returns {WorkerState} worker状态
   */
  getState(): WorkerState {
    return this.state;
  }

  /**
   * 获取该worker上次工作结束时间
   *
   * @returns {number} 上次工作结束时间
   */
  getLastBusyTime(): number {
    return this.lastBusyTime;
  }

  /**
   * 获取该worker的id
   *
   * @returns {number} worker的id
   */
  getId(): number {
    return this.id;
  }

  /**
   * 终止worker
   *
   * @param callback 终止worker后的回调函数
   */
  terminate(callback: Function): void {
    this.setState(WorkerState.DEAD);
    this.setLastBusyTime(Date.now());
    this.worker.terminate().then(callback());
  }

  /**
   * 设置该worker的状态
   *
   * @param state 待设置的状态
   */
  setState(state: WorkerState): void {
    this.state = state;
  }

  /**
   * 设置该worker上次工作结束时间
   *
   * @param time 上次工作结束时间
   */
  setLastBusyTime(time: number): void {
    this.lastBusyTime = time;
  }

  /**
   * 执行任务单元
   *
   * @param work 待执行的任务单元
   * @returns {boolean} 是否执行
   */
  doWork(work: Work): boolean {
    if (this.state === WorkerState.IDLE) {
      this.setState(WorkerState.BUSY);
      this.curWorkId = work.getId();
      this.curTaskInfo = {
        hasSideEffects: work.hasSideEffects(),
        preludeDeps: work.getPreludeDeps(),
      };
      this.worker.postMessage({
        id: work.getId(),
        workPath: work.getWorkPath(),
        inputData: work.getInputData(),
        exitAfterDone: work.hasSideEffects(),
      });
      return true;
    }
    return false;
  }

  /**
   * 获取该worker当前正在执行的工作单元id
   */
  getCurWorkId(): string | undefined {
    return this.curWorkId;
  }

  /**
   * 将当前正在执行的工作单元id设为undefined
   */
  cancelCurWorkId(): void {
    this.curWorkId = undefined;
  }

  isMeltdown(): boolean {
    return this.melted;
  }

  meltdown() {
    this.melted = true;
  }

  /**
   * 获取该线程当前执行的任务单元的信息
   *
   * @returns {TaskInfo | undefined} 当前执行的任务单元的信息
   */
  getCurTaskInfo(): TaskInfo | undefined {
    return this.curTaskInfo;
  }

  /**
   * 该线程当前是否存在缓存内容
   */
  hasCache(): boolean {
    return this.cacheSize > 0;
  }

  /**
   * 更新此线程当前的缓存项数量
   *
   * @param cacheSize 当前缓存项的数量
   */
  updateCacheSize(cacheSize: number) {
    this.cacheSize = cacheSize;
  }

  sendMessageToWorker(message: any) {
    this.worker.postMessage(message);
  }
}
